package componentes;

import items.BetItem;
import items.BetSideItem;
import items.EntityItem;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import model.Bet;
import model.BetSide;
import model.Entity;
import model.Group;
import model.Member;
import model.User;
import android.app.betmein.R;
import android.framework.binding.BindableList;
import android.framework.binding.BindableValue;
import android.framework.binding.IObservable;

public class Mapper {
	private static Mapper instance = new Mapper();
	
	public UserConvertor userConvertor = new UserConvertor();
	public GroupConvertor groupConvertor = new GroupConvertor();
	public MemberConvertor memberConvertor = new MemberConvertor();
	public BetSideConvertor betSideConvertor = new BetSideConvertor();
	public BetConvertor betConvertor = new BetConvertor();
	
	public static Mapper getInstance(){
		return instance;
	}
	
	private Mapper(){
		
	}
	
	public EntityItem[] map(Entity[] entities){
		EntityItem[] result = new EntityItem[entities.length];
		for (int i = 0; i < result.length; i++) {
			result[i] = map(entities[i]);
		}
		return result;
	}
	
	public EntityItem map(Entity entity){
		if(entity instanceof Group){
			return map((Group) entity);
		}
		else if(entity instanceof User){
			return map((User) entity);
		}
		else{
			throw new IllegalArgumentException("can't recognized entity type of " + entity.getClass().getSimpleName() );
		}
	}
	
	public EntityItem map(Group group){
		return groupConvertor.convert(group);
	}
	
	public EntityItem map(User user){
		return userConvertor.convert(user);
	}
	
	public EntityItem map(Member member){
		return memberConvertor.convert(member);
	}
	
	public BetSideItem map(BindableValue<BetSide> betSide){
		return betSideConvertor.convert(betSide);
	}
	
	public BetItem map(Bet bet){
		return betConvertor.convert(bet);
	}
	
	
	public BindableList<EntityItem> map(BindableList<Member> list){
		return map(list, memberConvertor);
	}
	
	
//	public BindableList<BetSideItem> map(BindableList<BetSide> list){
//		return map(list, betSideConvertor);
//	}
	
	public <T extends IObservable<Object>,G extends IObservable<Object>> BindableList<T> map(Collection<G> list, IConvertor<G, T> convertor){
		BindableList<T> result = new BindableList<T>();
		for (G o : list) {
			result.add(convertor.convert(o));
		}
		return result;
	}
	
	public <T, G> List<T> castList(List<G> list, IConvertor<G, T> convertor){
		List<T> result = new ArrayList<T>();
		for (G o : list) {
			result.add(convertor.convert(o));
		}
		return result;
	}
	
	public class UserConvertor implements IConvertor<User, EntityItem>{

		public EntityItem convert(User user) {
			EntityItem itemEntity = new EntityItem(user);
			itemEntity.getCenteralTextView().setText(user.getDescription().getText());
			itemEntity.setRightImageButton(R.drawable.right_image_button_invite);
			return itemEntity;
		}
		
	}
	
	
	public class BetSideConvertor implements IConvertor<BindableValue<BetSide>, BetSideItem>{

		public BetSideItem convert(BindableValue<BetSide> side) {
			BetSideItem itemSide = new BetSideItem(side); 
			return itemSide;
		}
		
	}
	
	public class GroupConvertor implements IConvertor<Group, EntityItem>{

		public EntityItem convert(Group group) {
			EntityItem itemEntity = new EntityItem(group);
			itemEntity.getCenteralTextView().setText(group.getDescription().getText());
			itemEntity.setRightImageButton(R.drawable.right_view_button_create_bet);
			return itemEntity;
		}
		
	}

	public class MemberConvertor implements IConvertor<Member, EntityItem>{
		public EntityItem convert(Member member) {
			EntityItem itemEntity = new EntityItem(member.getUser());
			itemEntity.getCenteralTextView().setText(member.getMoneybag().getMoneyAmount().toString());
			itemEntity.setRightImageButton(R.drawable.right_image_button_invite);
			return itemEntity;
		}
	}
	
	public class BetConvertor implements IConvertor<Bet, BetItem>{
		private Mapper.BetSideConvertor betSideconvertor = new Mapper.BetSideConvertor();
		public BetItem convert(Bet bet) {
			BetItem item = new BetItem(bet);
			item.setBetSides(castList(bet.getBetSides(), betSideconvertor));
			return item;
		}
	}

}
